<?php
/**
 * Created by PhpStorm.
 * User: crash
 * Date: 2018/5/30
 * Time: 11:09
 */

namespace App\Services\Authorize;

use App\Models\ServerSettings\Secret;
use App\Services\ResponseCode;
use App\Services\User\{ApiServer, CmServer, CpServer, CrServer, EsServer, RobotServer};


class ServerSignature extends BaseSignature implements AuthorizeInterface
{

    protected $secret;

    protected $source;

    protected $defaultKeyName;

    const SIGNATURE_HEADER_KEYS = ['keyname', 'timestamp', 'source', 'nonce', 'auth-type'];

    const DEFAULT_URI = [
        'server/signkey',
        'enterprise/get_by_outline_number'
    ];//默认密钥路由

    const SOURCE_SERVER_MAP = [
        'server.es'    => EsServer::class,
        'server.cp'    => CpServer::class,
        'server.cr'    => CrServer::class,
        'server.api'   => ApiServer::class,
        'server.robot' => RobotServer::class
    ];

    public function __construct()
    {
        $this->source = request()->header('source');
        $serverName = explode('.', $this->source);
        $this->defaultKeyName = implode('_', [$serverName[1], 'cm', 'default_secret']);
    }

    /**
     * @return null
     * 认证用户信息
     */
    public function getUser()
    {
        $methods = get_class_methods($this);
        foreach ($methods as $method) {
            if (starts_with($method, '_validate')) {
                $this->$method();
            }
        }
        if ($this->validateSignature()) {
            $server = self::SOURCE_SERVER_MAP[$this->source];
            return new $server;
        }
        return null;
    }

    /**
     * @throws \App\Exceptions\ApiException
     * 校验签名键名
     */
    protected function _validateKeyName(): void
    {
        if (!request()->header('keyname')) {
            api_exception(ResponseCode::KEYNAME_IS_MUST);
        }
        $prefix = str_replace('_default_secret', '', $this->defaultKeyName);
        if (!starts_with(request()->header('keyname'), $prefix)) {
            api_exception(ResponseCode::KEYNAME_ERROR);
        }

        if ((!$this->isDefaultUri()) && $this->isDefaultKeyname()) {
            api_exception(ResponseCode::KEYNAME_NOT_ALLOW);
        }

        if (!$this->secret = $this->getSecretKey()) {
            api_exception(ResponseCode::KEYNAME_NOT_EXISTS);
        }
    }

    /**
     * @return array
     * 获取参与签名的头部参数
     */
    protected function getSignatureHeadKeys(): array
    {
        return self::SIGNATURE_HEADER_KEYS;
    }

    /**
     * 获取签名密钥
     * @return mixed
     */
    protected function getSignatureKey(): ?string
    {
        return $this->secret['value'];
    }


    /**
     * 判断密钥是否存在
     * @return bool
     */
    protected function getSecretKey()
    {
        return Secret::where('name', request()->header('keyname'))->first();
    }

    /**
     * 判断是否默认签名
     * @return bool
     */
    protected function isDefaultKeyname()
    {
        return (request()->header('keyname') == $this->defaultKeyName);
    }

    /**
     * 判断是否默认路由
     * @return bool
     */
    protected function isDefaultUri()
    {
        return in_array(request()->route()->uri, self::DEFAULT_URI);
    }

}
